#pragma once

#include <sstream>
// #include <set>
class CLogStream
{
public:
	CLogStream(const char* szFileName,uint32_t dwLine,const int level );
	~CLogStream();
	template<int ARR_LEN>
	CLogStream& operator << ( const char (&sz)[ARR_LEN] )
	{
		m_oss << sz;
		return *this;
	}
	template<class T>
	CLogStream& operator << ( const T &obj );
	typedef std::basic_ostream<char, std::char_traits<char> >&
	FUN_ENDL(std::basic_ostream<char, std::char_traits<char> >& _Ostr);
	static FUN_ENDL* endl(){ return std::endl;}
private:
	//CString m_strLog;
	std::ostringstream m_oss;
	const std::string m_strFileName;
	const uint32_t m_dwLine;
	const int	m_level;
};

#define BEGIN_LOG_OBJ_DEBUG \
{\
	CLogStream objLogToFile(   __FILE__ , __LINE__ , 0);\
	objLogToFile

#define BEGIN_LOG_OBJ_INFO \
{\
	CLogStream objLogToFile(   __FILE__ , __LINE__ , 1);\
	objLogToFile

#define BEGIN_LOG_OBJ_WARN \
{\
	CLogStream objLogToFile(   __FILE__ , __LINE__ , 2);\
	objLogToFile


#define BEGIN_LOG_OBJ_ERROR \
{\
	CLogStream objLogToFile(   __FILE__ , __LINE__ , 3);\
	objLogToFile

#define END_LOG_OBJ "";}
void writeLog(const char*);
#define CHECK( e ) if( !(e)) { BEGIN_LOG_OBJ_ERROR << ( #e ) << END_LOG_OBJ ; return ;}
#define CHECK_PTR( e ) if( NULL == (e)) { BEGIN_LOG_OBJ_ERROR << ( #e ) << END_LOG_OBJ ; return ;}
#define CHECKF( e ) if( !(e)) { BEGIN_LOG_OBJ_ERROR << ( #e ) << END_LOG_OBJ ; return false ;}
#define CHECKNULL( e ) if( !(e)) { BEGIN_LOG_OBJ_ERROR << ( #e ) << END_LOG_OBJ ; return NULL;}
#define CHECKF_PTR( e ) if( NULL == (e)) { BEGIN_LOG_OBJ_ERROR << (#e) << END_LOG_OBJ ; return false; }
#define CHECKNULL_PTR( e ) if( NULL == (e)) { BEGIN_LOG_OBJ_ERROR << ( #e ) << END_LOG_OBJ ; return NULL; }
#define CHECK0_PTR( e ) if( nullptr == (e)) { BEGIN_LOG_OBJ_ERROR << ( #e ) << END_LOG_OBJ ; return 0; }
#define CHECK0( e ) if( !(e) ) { BEGIN_LOG_OBJ_ERROR << ( #e ) << END_LOG_OBJ ; return 0; }
#define CHECK_HR( e ) CHECK( SUCCEEDED( e ) ) 
#define CHECKF_HR( e ) CHECKF( SUCCEEDED( e ) ) 
#define IF_NOT( e ) if( (e) ? false : (writeLog( #e ) , true)  ) 
#define IF_NOT_PTR( e_ptr ) IF_NOT( NULL != (e_ptr) )
#define IF_NOT_HR( e ) IF_NOT( SUCCEEDED( e ) )
#define IF_OK( e ) if( (e) ? true : (writeLog( #e ) ,false)  )
#define IF_OK_PTR( e ) IF_OK( NULL != (e) )
#define IF_OK_HR( e ) IF_OK( SUCCEEDED( e ) )
#define VERIFY_LOG( e ) {if( !(e)) { BEGIN_LOG_OBJ_ERROR << ( #e ) << END_LOG_OBJ ; }}
// #define VERIFY_LOG_CRITICAL_ERR( e ) {if( !(e)) { LOG_ERROR( #e ) ; }}

// template< typename CONT >//20201010
// bool Found( CONT &c , const typename CONT::value_type &refV )
// {
// 	return c.end() != std::find( c.begin() , c.end() , refV );
// }

template<class KEY,class VALUE>//20201010
bool FoundMap( const std::map<KEY,VALUE> &c , const KEY &refKey)
{
	return c.end() != c.find( refKey );
}

// template<class KEY>//20201010
// bool FoundSet( const std::set<KEY> &c , const KEY &refKey)
// {
// 	return c.end() != c.find( refKey );
// }


// template<typename T,int ARR_LEN >//20201019
// int FindInArr( const T (&arr)[ARR_LEN] , const uint16_t wVailidItemCount , const T &refV )
// {
// 	IF_NOT( ARR_LEN >= wVailidItemCount )
// 		return ARR_LEN;
// 	return std::find( arr , arr+wVailidItemCount , refV )-arr;
// }
// template<typename T, class T_PRED >
// int FindIfInArr( const T arr[] , const int nArrLen , const T_PRED &refPred )
// {
// 	return std::find_if( arr , arr+nArrLen , refPred )-arr;
// }
// template<typename T, class T_PRED ,int LEN>
// int FindIfInArr( const T (&arr)[LEN] , const T_PRED &refPred )
// {
// 	return std::find_if( arr , arr+LEN , refPred )-arr;
// }

// template<typename T, class T_PRED >
// bool IsFindIfInArr( T arr[] , const int nArrLen , const T_PRED &refPred )
// {
// 	return nArrLen>FindIfInArr( arr ,nArrLen,  refPred );
// }
// template<typename T,int ARR_LEN >//20201019
// bool ArrContains(const T (&arr)[ARR_LEN] , const uint16_t wVailidItemCount ,const T &refV )
// {
// 	CHECKF( ARR_LEN >= wVailidItemCount );
// 	return wVailidItemCount>FindInArr( arr , wVailidItemCount, refV );
// }
// template<typename T,int ARR_LEN >//20201019
// int FindInArr( const T (&arr)[ARR_LEN] , const T &refV )
// {
// 	return FindInArr( arr , ARR_LEN , refV );
// }

// template<typename T,int ARR_LEN >//20201124
// inline int ArrLen( const T (&arr)[ARR_LEN] )
// {
// 	return ARR_LEN ;
// }

// #define GET_ARR_LEN(arr ) (std::extent<decltype( arr ), 0>::value)
// #define GET_ARR_LEN_1(arr ) (std::extent<decltype( arr ), 1>::value)

// #define GET_ARR_LEN_OLD( arr ) (sizeof(arr)/sizeof(arr[0]))
// // 编译期约束 20201125
// #define STATIC_ASSERT( e ) {struct S_STATIC_ASSERT_INT{int ai[(e)?1:-1];};};
// #define GLOBAL_STATIC_ASSERT( e ) void StaticConstrait( int ai[(e)?1:-1] ); 

// template<typename T,int ARR_LEN >//20201124
// inline int ArrSizeInBytes( const T (&arr)[ARR_LEN] )
// {
// 	STATIC_ASSERT(0<ARR_LEN);
// 	return ARR_LEN*sizeof(arr[0]) ;
// }

// template<typename T,int ARR_LEN >//20201019
// bool ArrContains( const T (&arr)[ARR_LEN] , const T &refV )
// {	
// 	return ArrContains( arr ,ARR_LEN,  refV );
// }


template<>
inline CLogStream& CLogStream::operator << ( const uint8_t &obj )//20201230
{
	m_oss << (int)obj;
	return *this;
}

template<> 
inline CLogStream& CLogStream::operator << ( const int8_t &obj )
{
	m_oss << (int)obj;
	return *this;	
}

template<class T>
CLogStream& CLogStream::operator << ( const T &obj )
{
	m_oss << obj;
	return *this;
}


// template <class T,int LEN>
// static void ZeroPodArr(T (&arr)[LEN])
// {
// 	STATIC_ASSERT(std::is_pod<T>::value );
// 	// MUST_BE_POD(T);
// 	for( int i=0 ; i<LEN ; ++i)
// 		memset(&arr[i],0, sizeof(arr[0]));
// }


// template<int LEN>
// void SafeStringCopy( char (&szDest)[LEN] , const char *pSrc)
// {
//     CHECK_PTR( pSrc );
//     strncpy( szDest, pSrc, LEN );
//     szDest[LEN-1]=0;
// }